package com.example.service_consumer.controller;

//import jakarta.annotation.Resource;
import javax.annotation.Resource;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.service_consumer.remoteService.ProviderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;


@RestController
public class HelloController {

    //    @Resource(name = "abc")
//    @Autowired
    //@Resource(name = "customRestTemplate")
    @Autowired
    private RestTemplate restTemplate;


    /*
    * Openfeign
    *
    */
    @Autowired
    ProviderService providerService;

    @GetMapping("/consumer/openfeign")
    public String hiOpenfeign(){
        //String providerBack = restTemplate.getForObject("http://service-provider/provider/openfeign", String.class);
        //String providerBack = restTemplate.getForObject("http://localhost:8081/provider/openfeign", String.class);
        String providerBack = providerService.hello();
        return "consumer is here. " + providerBack;
    }

    //通过打印port来测试负载均衡

    @GetMapping("/consumer/hello")
    public String hello() {

        //String providerBack = restTemplate.getForObject("http://service-provider/provider/hello", String.class);
        String providerBack = restTemplate.getForObject("http://localhost:8081/provider/hello", String.class);
        return "consumer is here. " + "get Msg from " + providerBack;

    }

    @GetMapping("/say/hi")
    public String hi(){return "hi consumer";}

    /*
    *4、请求超时
    *
    * */
    @GetMapping("/consumer/timeOut")
    public String requestTimeOut(){
        String providerBack = providerService.requestTimeOut();
        return "consumer is here. " + providerBack;
    }

    /*
    * lesson07:sentinel
    *
    * 1：限流规则
    *  */
    @SentinelResource(value = "hiMySentinel", blockHandler = "helloLimit")
    @GetMapping("/consumer/sentinel")
    public String hiSentinel(){
        //String providerBack = restTemplate.getForObject("http://service-provider/provider/openfeign", String.class);
        //String providerBack = restTemplate.getForObject("http://localhost:8081/provider/openfeign", String.class);
        //String providerBack = providerService.hello();
        String providerBack = "self";
        return "consumer is here. " + "get Msg from " + providerBack;
    }

    public String helloLimit(BlockException ex) {
        return "{\"code\":\"500\",\"msg\": \"" + "服务流量控制处理\"}" + " : " + ex.getMessage();
    }

    /*
     * lesson07:sentinel
     *
     * 2：熔断规则（慢调用）
     *  */
    @SentinelResource(value="responseSlow", fallback = "responseSlowFB")
    @GetMapping("/consumer/responseSlow")
    public String responseSlow() {
        int sleepCount = (int)(1+Math.random()*1000);
        try {
            Thread.sleep(sleepCount);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "consumer is here. " + "get Msg from responseSlow!!!: " + sleepCount + " ms";
    }

    public String responseSlowFB(Throwable throwable) {
        return "{\"code\":\"500\",\"msg\": \"" + "服务熔断控制处理：慢调用\"}" + " : " + throwable.getMessage();

    }

    /*
     * lesson07:sentinel
     *
     * 2：熔断规则（异常）
     *  */
    @SentinelResource(value="responseException", fallback = "responseExceptionFB")
    @GetMapping("/consumer/responseException")
    public String responseException() {
        int randValue = (int)(1+Math.random()*1000);
        if (0 == randValue%2) {
            throw new RuntimeException("熔断异常，随机值为"+ randValue);
        } else {
            return "consumer is here. " + "get Msg from responseException!!!: " + randValue;
        }
    }

    public String responseExceptionFB(Throwable throwable) {
        //进入此函数存在两种情况：1. 函数抛出异常 2. 熔断规则满足
        //目前发现：如果是sentinel 异常规则进入，则throwable.getMessage() 为null
        return "{\"code\":\"500\",\"msg\": \"" + "服务熔断控制处理：异常\"}"
                + " : " + throwable.getMessage() + ". " + throwable.getCause();

    }

    /*
    * lesson08:JMeter Test And Jmeter Cluster Test
    *
    * */
    @GetMapping("/consumer/helloWithReqParam")
    public String helloWithReqParam(String name, int age) {
        return "name: " + name + ", age: " + age;
    }

    @PostMapping("/consumer/helloWithReqBody")
    public String helloWithReqBody(@RequestBody String name, Integer age) {
        System.out.println("name: " + name + ", age: " + age);
        return "name: " + name + ", age: " + age;
    }

}
